package com.hsteach.service.rota;

import java.util.*;
import java.util.stream.Collectors;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hsteach.common.core.domain.model.AuthInfo;
import com.hsteach.common.exception.ServiceException;
import com.hsteach.common.utils.DateUtils;
import com.hsteach.common.utils.SecurityUtils;
import com.hsteach.dao.domain.rota.RotaDetail;
import com.hsteach.dao.domain.rota.RotaFiles;
import com.hsteach.dao.domain.rota.RotaPerson;
import com.hsteach.dao.mapper.rota.RotaDetailMapper;
import com.hsteach.dao.mapper.rota.RotaFilesMapper;
import com.hsteach.dao.mapper.rota.RotaPersonMapper;
import com.hsteach.enums.BooleanEnum;
import com.hsteach.web.controller.rota.dto.AddRotaRecordDto;
import com.hsteach.web.controller.rota.dto.ListRotaRecordDto;
import com.hsteach.web.controller.rota.vo.ListRotaRecordVo;
import com.hsteach.web.controller.rota.vo.MineRecordVo;
import com.hsteach.web.controller.rota.vo.RotaRecordVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hsteach.dao.mapper.rota.RotaRecordMapper;
import com.hsteach.dao.domain.rota.RotaRecord;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 值班记录Service业务层处理
 * 
 * @author fanxquer
 * @date 2023-10-22
 */
@Service
public class RotaRecordService
{
    @Autowired
    private RotaRecordMapper rotaRecordMapper;

    @Autowired
    private RotaDetailMapper rotaDetailMapper;

    @Autowired
    private RotaPersonMapper rotaPersonMapper;

    @Autowired
    private RotaFilesMapper rotaFilesMapper;

    /**
     * 查询值班记录
     * 
     * @param id 值班记录主键
     * @return 值班记录
     */
    public List<RotaRecordVo> selectRotaRecordById(Long id)
    {
        RotaRecord query = new RotaRecord();
        query.setRotaDetailId(id);
        List<RotaRecord> rotaRecords = rotaRecordMapper.selectRotaRecordList(query);

        List<Long> recordIds = rotaRecords.stream().map(RotaRecord::getId).collect(Collectors.toList());
        RotaFiles fileQuery = new RotaFiles();
        fileQuery.setRotaRecordIds(recordIds);
        Map<Long, List<RotaFiles>> fileMap = rotaFilesMapper.selectRotaFilesList(fileQuery).stream().collect(Collectors.groupingBy(RotaFiles::getRotaRecordId));
        List<RotaRecordVo> ret = rotaRecords.stream().map(e -> {
            RotaRecordVo vo = new RotaRecordVo();
            BeanUtils.copyProperties(e, vo);
            vo.setFiles(fileMap.getOrDefault(e.getId(), Lists.newArrayList()));
            vo.setWeekStr(getWeekStr(e.getRecordTime()));
            return vo;
        }).collect(Collectors.toList());
        return ret;
    }

    private String getWeekStr(Date date) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        //一周第一天是否为星期天
        boolean isFirstSunday = (instance.getFirstDayOfWeek() == Calendar.SUNDAY);
        //获取周几
        int weekDay = instance.get(Calendar.DAY_OF_WEEK);
        //若一周第一天为星期天，则-1
        if(isFirstSunday){
            weekDay = weekDay - 1;
            if(weekDay == 0){
                weekDay = 7;
            }
        }
        switch (weekDay) {
            case 1:
                return "星期一";
            case 2:
                return "星期二";
            case 3:
                return "星期三";
            case 4:
                return "星期四";
            case 5:
                return "星期五";
            case 6:
                return "星期六";
            case 7:
                return "星期日";
        }
        return "";
    }

    /**
     * 查询值班记录列表
     * 
     * @param rotaRecord 值班记录
     * @return 值班记录
     */
    public List<RotaRecord> selectRotaRecordList(RotaRecord rotaRecord)
    {
        return rotaRecordMapper.selectRotaRecordList(rotaRecord);
    }

    public List<ListRotaRecordVo> listRecord(ListRotaRecordDto dto) {
        RotaDetail query = new RotaDetail();
        BeanUtils.copyProperties(dto, query);
        query.setDelStatus(BooleanEnum.TRUE.getCode());
        query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        List<RotaDetail> rotaDetails = rotaDetailMapper.selectRotaDetailList(query);
        if (rotaDetails.size() == 0) {
            return Lists.newArrayList();
        }

        List<Long> detailIds = rotaDetails.stream().map(RotaDetail::getId).collect(Collectors.toList());
        RotaRecord recordQuery = new RotaRecord();
        recordQuery.setRotaDetailIds(detailIds);
        List<RotaRecord> rotaRecords = rotaRecordMapper.selectRotaRecordList(recordQuery);
        Map<Long, List<RotaRecord>> recordMap = rotaRecords.stream().collect(Collectors.groupingBy(RotaRecord::getRotaDetailId));

        RotaPerson personQuery = new RotaPerson();
        personQuery.setRotaDetailIds(detailIds);
        List<RotaPerson> rotaPeople = rotaPersonMapper.selectRotaPersonList(personQuery);
        Map<Long, List<RotaPerson>> personMap = rotaPeople.stream().collect(Collectors.groupingBy(RotaPerson::getRotaDetailId));

        Map<Long, List<RotaFiles>> fileMap;
        if (!CollectionUtils.isEmpty(rotaRecords)) {
            RotaFiles fileQuery = new RotaFiles();
            fileQuery.setRotaRecordIds(rotaRecords.stream().map(RotaRecord::getId).collect(Collectors.toList()));
            fileMap = rotaFilesMapper.selectRotaFilesList(fileQuery).stream().collect(Collectors.groupingBy(RotaFiles::getRotaRecordId));
        } else {
            fileMap = Maps.newHashMap();
        }


        List<ListRotaRecordVo> ret = rotaDetails.stream().map(e -> {
            ListRotaRecordVo vo = new ListRotaRecordVo();
            BeanUtils.copyProperties(e, vo);
            List<RotaPerson> persons = personMap.getOrDefault(e.getId(), Lists.newArrayList());
            Map<String, RotaRecord> personRecordMap = recordMap.getOrDefault(e.getId(), Lists.newArrayList()).stream().collect(Collectors.toMap(RotaRecord::getPersonId, k -> k, (v1, v2) -> v2));
            List<RotaRecordVo> records = persons.stream().map(k -> {
                RotaRecordVo recordVo = new RotaRecordVo();
                BeanUtils.copyProperties(k, recordVo);
                if (personRecordMap.containsKey(k.getPersonId())) {
                    RotaRecord rotaRecord = personRecordMap.get(k.getPersonId());
                    BeanUtils.copyProperties(rotaRecord, recordVo);
                    recordVo.setRecordFlg(BooleanEnum.TRUE.getCode());
                    recordVo.setFiles(fileMap.getOrDefault(rotaRecord.getId(), Lists.newArrayList()));
                } else {
                    recordVo.setRecordFlg(BooleanEnum.FALSE.getCode());
                }
                return recordVo;
            }).collect(Collectors.toList());
            vo.setRecords(records);
            return vo;
        }).collect(Collectors.toList());

        return ret;
    }

    public List<MineRecordVo> listMine(ListRotaRecordDto dto) {
        RotaDetail query = new RotaDetail();
        BeanUtils.copyProperties(dto, query);
        query.setDelStatus(BooleanEnum.TRUE.getCode());
        query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        List<RotaDetail> rotaDetails = rotaDetailMapper.selectRotaDetailList(query);
        if (rotaDetails.size() == 0) {
            return Lists.newArrayList();
        }

        List<Long> detailIds = rotaDetails.stream().map(RotaDetail::getId).collect(Collectors.toList());
        RotaRecord recordQuery = new RotaRecord();
        recordQuery.setRotaDetailIds(detailIds);
        List<RotaRecord> rotaRecords = rotaRecordMapper.selectRotaRecordList(recordQuery);
        Map<Long, List<RotaRecord>> recordMap = rotaRecords.stream().collect(Collectors.groupingBy(RotaRecord::getRotaDetailId));

        RotaPerson personQuery = new RotaPerson();
        personQuery.setRotaDetailIds(detailIds);
        List<RotaPerson> rotaPeople = rotaPersonMapper.selectRotaPersonList(personQuery);
        String myPersonId = SecurityUtils.getAuthInfo().getPersonId();
        Map<Long, RotaPerson> personMap = rotaPeople.stream().filter(e -> myPersonId.equals(e.getPersonId()))
                .collect(Collectors.toMap(RotaPerson::getRotaDetailId, e -> e, (v1, v2) -> v2));

        List<MineRecordVo> ret = rotaDetails.stream().filter(e -> personMap.containsKey(e.getId()))
                .map(e -> {
                    MineRecordVo vo = new MineRecordVo();
                    vo.setId(e.getId());
                    vo.setDutyDate(e.getDutyDate());
                    if (recordMap.containsKey(e.getId()) && recordMap.get(e.getId()).stream().map(RotaRecord::getPersonId).collect(Collectors.toList()).contains(myPersonId)) {
                        vo.setRecordFlg(BooleanEnum.TRUE.getCode());
                    } else {
                        vo.setRecordFlg(BooleanEnum.FALSE.getCode());
                    }
                    return vo;
                }).sorted(Comparator.comparing(MineRecordVo::getDutyDate)).collect(Collectors.toList());
        return ret;
    }

    /**
     * 新增值班记录
     * 
     * @param rotaRecord 值班记录
     * @return 结果
     */
    public int insertRotaRecord(RotaRecord rotaRecord)
    {
        rotaRecord.setCreateTime(DateUtils.getNowDate());
        return rotaRecordMapper.insertRotaRecord(rotaRecord);
    }

    @Transactional(rollbackFor = Exception.class)
    public int add(AddRotaRecordDto dto)
    {
        AuthInfo authInfo = SecurityUtils.getAuthInfo();
        RotaRecord query = new RotaRecord();
        query.setRotaDetailId(dto.getId());
        query.setPersonId(authInfo.getPersonId());
        List<RotaRecord> rotaRecords = rotaRecordMapper.selectRotaRecordList(query);
        if (rotaRecords.size() > 0) {
            throw new ServiceException("请勿重复填写");
        }

        RotaRecord record = new RotaRecord();
        record.setRotaDetailId(dto.getId());
        record.setRecordTime(new Date());
        record.setRecordContent(dto.getRecordContent());
        record.setOrgCode(authInfo.getOrgCode());
        record.setPersonId(authInfo.getPersonId());
        record.setPersonName(authInfo.getName());
        record.setUnusualFlg(dto.getUnusualFlg());
        record.setCreateBy(authInfo.getPersonId());
        int i = rotaRecordMapper.insertRotaRecord(record);
        if (i <= 0) {
            throw new ServiceException("新增记录失败");
        }

        List<RotaFiles> files = dto.getFiles().stream().map(e -> {
            RotaFiles file = new RotaFiles();
            BeanUtils.copyProperties(e, file);
            file.setRotaRecordId(record.getId());
            return file;
        }).collect(Collectors.toList());
        if (files.size() > 0) {
            rotaFilesMapper.batchInsert(files);
        }
        return i;
    }

    @Transactional(rollbackFor = Exception.class)
    public int update(AddRotaRecordDto dto)
    {
        AuthInfo authInfo = SecurityUtils.getAuthInfo();
        RotaRecord query = new RotaRecord();
        query.setRotaDetailId(dto.getId());
        query.setPersonId(authInfo.getPersonId());
        List<RotaRecord> rotaRecords = rotaRecordMapper.selectRotaRecordList(query);
        if (rotaRecords.size() == 0) {
            throw new ServiceException("未查找到记录");
        }

        RotaRecord record = rotaRecords.get(0);

        record.setRecordTime(new Date());
        record.setRecordContent(dto.getRecordContent());
        record.setPersonId(authInfo.getPersonId());
        record.setPersonName(authInfo.getName());
        record.setUnusualFlg(dto.getUnusualFlg());
        record.setUpdateBy(authInfo.getPersonId());
        int i = rotaRecordMapper.updateRotaRecord(record);
        if (i <= 0) {
            throw new ServiceException("修改记录失败");
        }

        List<RotaFiles> files = dto.getFiles().stream().map(e -> {
            RotaFiles file = new RotaFiles();
            BeanUtils.copyProperties(e, file);
            file.setRotaRecordId(record.getId());
            return file;
        }).collect(Collectors.toList());
        rotaFilesMapper.deleteByRotaRecordId(record.getId());
        if (files.size() > 0) {
            rotaFilesMapper.batchInsert(files);
        }
        return i;
    }

    /**
     * 修改值班记录
     * 
     * @param rotaRecord 值班记录
     * @return 结果
     */
    public int updateRotaRecord(RotaRecord rotaRecord)
    {
        rotaRecord.setUpdateTime(DateUtils.getNowDate());
        return rotaRecordMapper.updateRotaRecord(rotaRecord);
    }

    /**
     * 批量删除值班记录
     * 
     * @param ids 需要删除的值班记录主键
     * @return 结果
     */
    public int deleteRotaRecordByIds(Long[] ids)
    {
        return rotaRecordMapper.deleteRotaRecordByIds(ids);
    }

    /**
     * 删除值班记录信息
     * 
     * @param id 值班记录主键
     * @return 结果
     */
    public int deleteRotaRecordById(Long id)
    {
        return rotaRecordMapper.deleteRotaRecordById(id);
    }
}
